home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 / Ham Radio 2000.iso / ham2000 / tcp_ip / ntp_src / ntp_pccl.c < prev    next >
C/C++ Source or Header  |  1992-04-03  |  6KB  |  242 lines

  1. /* $Header: ntp_pcclock.c,v 1.5 91/06/21 15:21:40 ath Exp $ */
  2. /*
  3.  * ntp_pcclock.c - routines for reading and adjusting NOS' ntp clock.
  4.  */
  5.  
  6. #include <stdio.h>
  7.  
  8. #include "global.h"
  9. #include "sockaddr.h"
  10. #include "timer.h"
  11.  
  12. #include "ntp_types.h"
  13. #include "ntp_syslog.h"
  14. #include "ntp_fp.h"
  15. #define    CLOCK_ADJ    4
  16.  
  17. extern int debug;
  18.  
  19. /*
  20.  * These routines (init_systime, get_systime, step_systime, adj_systime)
  21.  * implement an interface between the (more or less) system independent
  22.  * bits of NTP and the hacked NOS clock.  NOS now keeps time in NTP format,
  23.  * so this interface is much simpler than the Unix version.
  24.  */
  25.  
  26. /*
  27.  * Clock variables.  We limit the adjustment to (tsf_maxslew fractional sec)
  28.  * in one four second period.  As we are thus limited in the speed and
  29.  * precision with which we can adjust the
  30.  * clock, we compensate by keeping the known "error" in the system time
  31.  * in sys_offset.  This is added to timestamps returned by get_systime().
  32.  */
  33. unsigned long tsf_maxslew;    /* same as above, as long format */
  34. static l_fp sys_offset;        /* correction for current system time */
  35.  
  36. /*
  37.  * init_systime - initialize the system clock support code, return
  38.  *          clock precision.
  39.  *
  40.  * used in the same manner.  Tick is supposed to be the number of
  41.  * microseconds which are added to the system clock at clock interrupt
  42.  * time when the time isn't being slewed.  Tickadj is supposed to be
  43.  * the number of microseconds which are added or subtracted from tick when
  44.  * the time is being slewed.
  45.  *
  46.  * If either of these two variables is missing, or is there but is used
  47.  * for a purpose different than that described, you are SOL and may have
  48.  * to do some custom kludging.
  49.  *
  50.  * This really shouldn't be in here.
  51.  */
  52. void
  53. init_systime()
  54. {
  55.     u_long tickadj;
  56.     u_long tick;
  57.     u_long hz;
  58.  
  59.     /*
  60.      * Obtain the values.  There are both in NTP fractional seconds.
  61.      */
  62.     tickadj = get_tickadj();
  63.     tick = get_tick();
  64.  
  65.     /*
  66.      * Estimate hz from tick.  I'm cheating--since tick is an NTP fraction,
  67.      * this should be 0x100000000 / tick, but we can only do 32 bit math.
  68.      */
  69.     hz = 0xffffffffL / tick;
  70.  
  71.     /*
  72.      * Set the maximum slew based on tickadj and tick.  Note
  73.      * that maxslew is set slightly shorter than it needs to be as
  74.      * insurance that all slews requested will complete in CLOCK_ADJ
  75.      * seconds.
  76.      */
  77.     tsf_maxslew = tickadj * (hz - 1) * CLOCK_ADJ;
  78. #ifdef DEBUG
  79.     if (debug)
  80.         printf("tsf_maxslew = 0.%08lx\n", tsf_maxslew);
  81. #endif
  82.  
  83.     /*
  84.      * Set the current offset to 0
  85.      */
  86.     sys_offset.l_ui = sys_offset.l_uf = 0;
  87. }
  88.  
  89.  
  90. /*
  91.  * get_systime - return the system time in timestamp format
  92.  */
  93. void
  94. get_systime(ts)
  95.     l_fp *ts;
  96. {
  97. #ifndef SLEWALWAYS
  98.     /*
  99.      * Quickly get the time of day.
  100.      */
  101.     getntptimeofday (ts);
  102. #else  /* SLEWALWAYS */
  103.     /*
  104.      * Get the time of day and add in the current time offset.
  105.      * Then round appropriately.
  106.      */
  107.     getntptimeofday (ts);
  108.     L_ADD(ts, &sys_offset);
  109. #endif    /* SLEWALWAYS */
  110. }
  111.  
  112.  
  113. /*
  114.  * step_systime - do a step adjustment in the system time (at least from
  115.  *          NTP's point of view.
  116.  */
  117. void
  118. step_systime(ts)
  119.     l_fp *ts;
  120. {
  121. #ifndef SLEWALWAYS
  122.     extern char *lfptoa();
  123.     extern void stepntptime ();
  124.  
  125.     /*
  126.      * We can afford to be sloppy here since if this is called
  127.      * the time is really screwed and everything is being reset.
  128.      */
  129.     L_ADD(&sys_offset, ts);
  130.  
  131.     /* call the hardware-specific step routine. */
  132.     stepntptime (&sys_offset);
  133. #ifdef DEBUG
  134.     if (debug > 3)
  135.         printf("step: %s, sys_offset = %s\n",
  136.             lfptoa(&ts, 9), lfptoa(&sys_offset, 9));
  137. #endif
  138.     sys_offset.l_ui = sys_offset.l_uf = 0;
  139.     
  140. #else
  141.     /*
  142.      * Just add adjustment into the current offset.  The update
  143.      * routine will take care of bringing the system clock into
  144.      * line.
  145.      */
  146.     L_ADD(&sys_offset, ts);
  147. #endif    /* SLEWALWAYS */
  148. }
  149.  
  150.  
  151. /*
  152.  * adj_systime - called once every CLOCK_ADJ seconds to make system time
  153.  *         adjustments.
  154.  */
  155. void
  156. adj_systime(adj)
  157.     long adj;
  158. {
  159.     register unsigned long offset_i, offset_f;
  160.     int32 slew, leftover;
  161.     register int isneg = 0;
  162.     extern char *mfptoa();
  163.     extern char *umfptoa();
  164.  
  165.     /*
  166.      * Move the current offset into the registers
  167.      */
  168.     offset_i = sys_offset.l_ui;
  169.     offset_f = sys_offset.l_uf;
  170.  
  171.     /*
  172.      * Add the new adjustment into the system offset.  Adjust the
  173.      * system clock to minimize this.
  174.      */
  175.     M_ADDF(offset_i, offset_f, adj);
  176.     if (M_ISNEG(offset_i, offset_f)) {
  177.         isneg = 1;
  178.         M_NEG(offset_i, offset_f);
  179.     }
  180. #ifdef DEBUG
  181.     if (debug > 4)
  182.         printf("adj_systime(%s): offset = %s%s\n",
  183.             mfptoa((adj<0?-1L:0L), adj, 9), isneg?"-":"",
  184.             umfptoa(offset_i, offset_f, 9));
  185. #endif
  186.  
  187.     if (offset_i > 0 || offset_f >= tsf_maxslew) {
  188.         /*
  189.          * Slew is bigger than we can complete in
  190.          * the adjustment interval.  Make a maximum
  191.          * sized slew and reduce sys_offset by this
  192.          * much.
  193.          */
  194.         M_SUBUF(offset_i, offset_f, tsf_maxslew);
  195.         if (!isneg) {
  196.             slew = tsf_maxslew;
  197.         } else {
  198.             slew = -tsf_maxslew;
  199.             M_NEG(offset_i, offset_f);
  200.         }
  201.  
  202. #ifdef DEBUG
  203.         if (debug > 4)
  204.             printf(
  205.                 "maximum slew: %s%s, remainder = %s\n",
  206.                 isneg?"-":"", umfptoa(0L, tsf_maxslew, 9),
  207.                 mfptoa(offset_i, offset_f, 9));
  208. #endif
  209.     } else {
  210.         /*
  211.          * We can do this slew in the time period.
  212.          *
  213.          * Note that offset_i is guaranteed to be 0 here.
  214.          */
  215.         if (isneg) {
  216.             slew = -offset_f;
  217.         } else {
  218.             slew = offset_f;
  219.         }
  220.         offset_i = offset_f = 0;
  221. #ifdef DEBUG
  222.         if (debug > 4)
  223.             printf("slew: %s\n", mfptoa((slew<0?-1L:0L), slew, 9));
  224. #endif
  225.     }
  226.  
  227.     sys_offset.l_ui = offset_i;
  228.     sys_offset.l_uf = offset_f;
  229.  
  230.     if (slew == 0)
  231.         return;
  232.     if (leftover = adjtime (slew))  {
  233.         syslog(LOG_ERR, "Previous time adjustment didn't complete");
  234. #ifdef DEBUG
  235.         if (debug > 4)
  236.             printf(
  237.                 "Previous adjtime() incomplete, residual = %ld\n",
  238.                    leftover);
  239. #endif
  240.     }
  241. }
  242.